/* DataValue.cs -- 
   Copyright (C) 2008  Casey Marshall.

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or (at
your option) any later version.

This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.  */


using System;
using System.Text;
using SexpSharp;

namespace SexpSharp.RPC
{
	/// <summary>
	/// A blob of bytes.
	/// </summary>
	public sealed class DataValue : IValue
	{
		private byte[] _value;

		/// <summary>
		/// Constructs a new DataValue using the given value.
		/// </summary>
		///
		/// <param name="value">The bytes.</param>
		public DataValue(byte[] value)
		{
			this._value = (byte[]) value.Clone();
		}

		public DataValue(Expression expr)
		{
			List l = expr as List;
			if (l == null)
				throw new ArgumentException("must be a List", "expr");
			if (l.Count != 2 || !(l.First is Atom) || !(l.Second is Atom))
				throw new ArgumentException("list must have exactly two atoms");
			if (l.First.ToString() != "data")
				throw new ArgumentException("first item of list must be 'data'");
			_value = ((Atom) l.Second).Bytes;
		}

		/// <summary>
		/// The underlying value.
		/// </summary>
		public byte[] Value
		{
			get { return (byte[]) _value.Clone(); }
			set { _value = (byte[]) value.Clone(); }
		}

		public Expression ToExpression()
		{
			List list = new List();
			list.Add(new Atom("data"));
			list.Add(new Atom(_value));
			return list;
		}

		public override string ToString()
		{
			StringBuilder str = new StringBuilder();
			foreach (byte b in _value)
				str.Append(b.ToString("x2"));
			return str.ToString();
		}

		public bool Equals(IValue value)
		{
			if (value is DataValue)
			{
				byte[] val = ((DataValue) value)._value;
				if (_value.Length != val.Length)
					return false;
				for (int i = 0; i < _value.Length; i++)
				{
					if (_value[i] != val[i])
						return false;
				}
				return true;
			}
			return false;
		}

		public override bool Equals(object o)
		{
			if (o is IValue)
				return Equals((IValue) o);
			return false;
		}

		public override int GetHashCode()
		{
			return _value.GetHashCode();
		}
	}
}
